//
//  FFmpegTool.m
//  FFmpegTool
//
//  Created by woo on 2020/12/17.
//

#import "FFmpegTool.h"

#include "libavutil/opt.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
#include "ffmpeg.h"
//#include "x264iOS/include/x264.h"

@interface FFmpegTool ()

@property (nonatomic, assign) BOOL isRuning;
@property (nonatomic, assign) BOOL isBegin;
@property (nonatomic, assign) long long fileDuration;
@property (nonatomic, copy) void (^processBlock)(float process);
@property (nonatomic, copy) void (^completionBlock)(NSError *error);

@end

@implementation FFmpegTool

+ (FFmpegTool *)sharedManager {
    static dispatch_once_t once;
    static id instance;
    dispatch_once(&once, ^{
        instance = [self new];
    });
    return instance;
}


- (instancetype)init {
    
    self = [super init];
    if (self) {
        AVCodec *pCodec;
        pCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
        if (!pCodec) {
            NSLog(@"Can not find encoder!");
        }
    }
    return self;
}


- (void)cmdToMp4:(NSString *)inFile outFile:(NSString *)outFile
    processBlock:(void (^)(float process))processBlock
 completionBlock:(void (^)(NSError *error))completionBlock {
    
    self.processBlock = processBlock;
    self.completionBlock = completionBlock;
    self.isBegin = NO;
    
    //https://blog.csdn.net/happydeer/article/details/52610060
//https://blog.csdn.net/qq_44920947/article/details/109476656
//    NSString *cmdStr = [NSString stringWithFormat:@"ffmpeg -i %@ -c:v libx264 -preset veryslow -crf 18 -c:a copy %@",inFile,outFile];
    NSString *cmdStr = [NSString stringWithFormat:@"ffmpeg -i %@ -threads 10 -preset ultrafast -vcodec h264 %@",inFile,outFile];
    
    // 放在子线程运行
    [[[NSThread alloc] initWithTarget:self selector:@selector(runCmd:) object:cmdStr] start];
}

// 执行指令
- (void)runCmd:(NSString *)commandStr{
    // 判断转换状态
    if (self.isRuning) {
        NSLog(@"正在转换,稍后重试");
    }
    self.isRuning = YES;
    
    // 根据 !#$ 将指令分割为指令数组
    NSArray *argv_array = [commandStr componentsSeparatedByString:(@" ")];
    // 将OC对象转换为对应的C对象
    int argc = (int)argv_array.count;
    char** argv = (char**)malloc(sizeof(char*)*argc);
    for(int i=0; i < argc; i++) {
        argv[i] = (char*)malloc(sizeof(char)*1024);
        strcpy(argv[i],[[argv_array objectAtIndex:i] UTF8String]);
    }
    
    // 打印日志
    NSString *finalCommand = @"ffmpeg 运行参数:";
    for (NSString *temp in argv_array) {
        finalCommand = [finalCommand stringByAppendingFormat:@"%@",temp];
    }
    NSLog(@"%@",finalCommand);
    
    // 传入指令数及指令数组
    ffmpeg_main(argc,argv);
    
    // 线程已杀死,下方的代码不会执行
}

// 设置总时长
+ (void)setDuration:(long long)time {
    [FFmpegTool sharedManager].fileDuration = time;
}

// 设置当前时间
+ (void)setCurrentTime:(long long)time {
    FFmpegTool *mgr = [FFmpegTool sharedManager];
    mgr.isBegin = YES;
    
    if (mgr.processBlock && mgr.fileDuration) {
        float process = time/(mgr.fileDuration * 1.00);
        
        dispatch_async(dispatch_get_main_queue(), ^{
            mgr.processBlock(process);
        });
    }
}

// 转换停止
+ (void)stopRuning {
    FFmpegTool *mgr = [FFmpegTool sharedManager];
    NSError *error = nil;
    // 判断是否开始过
    if (!mgr.isBegin) {
        // 没开始过就设置失败
        error = [NSError errorWithDomain:@"转换失败,请检查源文件的编码格式!"
                                    code:0
                                userInfo:nil];
    }
    if (mgr.completionBlock) {
        dispatch_async(dispatch_get_main_queue(), ^{
            mgr.completionBlock(error);
        });
    }
    
    mgr.isRuning = NO;
}

@end

//https://www.jianshu.com/p/ecfbebadbe55
//格式转换
//ffmpeg -i mkv.mkv -acodec copy -vcodec copy newVideo.mp4
//ffmpeg -i wav.wav -ar 44100 -y outputmusic.aac
//
//视频转GIF
//ffmpeg -i mkv.mkv -ss 00:00:10 -t 10 -pix_fmt rgb24 -f gif -s vga gif.gif
//
//视频声音分离 与合成
//ffmpeg -i mp4.mp4 -f mp3 -vn mp3.mp3
//ffmpeg -i mp4.mp4 -an mp4No.mp4
//ffmpeg -i mp3.mp3 -i mp4No.mp4 -map 0:0 -map 1:0 -c:v copy -c:a libfaac sound.mp4
//
//旋转视频
//ffmpeg -i mp4.mp4 -vf transpose=2 transpose.mp4
//
//反转视频
//水平翻转 ：ffmpeg -i mp4.mp4 -vf hflip reversed.mp4
//垂直翻转 ：ffmpeg -i mp4.mp4 -vf vflip reversed.mp4
//
//合并视频
//ffmpeg -f concat -i filelist.txt -y -acodec copy -strict -2 toName
//
//水印字幕合成
//ffmpeg -i fromName -i fromOther -filter_complex [0:v][1:v]overlay=0:H-h:enable='between(t,0,1)'[tmp];[tmp][1:v]overlay=0:H-h:enable='between(t,3,4)' -t 7 -y -strict -2 toName
